<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            body {
                height: 100vh;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .frame {
                width: 800px;
                min-height: 200px;
                position: relative;
            }
            .frame:hover .circle {
                opacity: 1;
            }
            .circle {
                position: absolute;
                top: 0;
                left: 0;
                width: 200px;
                height: 200px;
                border: 5px solid rgb(0, 0, 0);
                box-shadow: 0 0 5px rgb(0, 0, 0);
                border-radius: 50%;
                overflow: hidden;
                cursor: pointer;
                opacity: 0;
            }
            .circle img {
                position: absolute;
                top: 0;
                left: 0;
            }
        </style>
    </head>
    <body>
        <div class="frame">
            <img src="封面.jpg" width="100%" /><!-- 小图片 -->
            <div class="circle">
                <!-- 放大镜 -->
                <img src="封面.jpg" />
            </div>
        </div>

        <script>
            /*  先获取元素，底层盒子，放大镜，放大镜里的大图 */
            var frame = document.querySelector('.frame');
            var circle = document.querySelector('.circle');
            var picture = document.querySelector('.circle img');

            /*  给底层盒子绑定一个鼠标移动的事件 */
            frame.addEventListener('mousemove', function (e) {
                /*  放大镜左右移动 */
                /*  获取鼠标距离左边距离 */
                let x = e.clientX;
                /*  获取底层盒子距离左边距离 */
                let left = frame.offsetLeft;
                /*  放大镜左右移动距离就是 x 减 left 再减去本身宽度一半 */
                let moveX = x - left - circle.offsetWidth / 2;
                /*  如果是移动距离是负数就等于零。相当于放大镜在底层盒子最左边时，不要让他跑出去 */
                if (moveX <= 0) moveX = 0;
                /* 以此类推，相当于放大镜在底层盒子最右边时，不要让他跑出去 */
                if (moveX >= frame.offsetWidth - circle.offsetWidth) moveX = frame.offsetWidth - circle.offsetWidth;
                /* 放大镜移动 */
                circle.style.left = moveX + 'px';
                /* 放大镜里大图片移动距离。就是按比例算，鼠标移动距离/小图宽度=大图移动距离/大图宽度  可以想象一下这个比例。*/
                let moveleft = ((moveX + circle.offsetWidth / 2) / frame.offsetWidth) * picture.offsetWidth - circle.offsetWidth / 2;

                /* 大图移动，向左移动，所以是负数 */
                picture.style.left = -moveleft + 'px';

                /* 放大镜上下移动，跟上面左右移动是一样的原理 */
                let y = e.clientY;
                let top = frame.offsetTop;
                let moveY = y - top - circle.offsetHeight / 2;
                if (moveY <= 0) moveY = 0;
                if (moveY >= frame.offsetHeight - circle.offsetHeight) moveY = frame.offsetHeight - circle.offsetHeight;

                circle.style.top = moveY + 'px';

                let movetop = ((moveY + circle.offsetHeight / 2) / frame.offsetHeight) * picture.offsetHeight - circle.offsetHeight / 2;

                picture.style.top = -movetop + 'px';
            });
        </script>
    </body>
</html>
